package cn.edu.xmu.oomall.share.service;

import cn.edu.xmu.oomall.core.util.Common;
import cn.edu.xmu.oomall.core.util.ReturnNo;
import cn.edu.xmu.oomall.core.util.ReturnObject;
import cn.edu.xmu.oomall.share.dao.ShareDao;
import cn.edu.xmu.oomall.share.microservice.ActivityService;
import cn.edu.xmu.oomall.share.microservice.GoodsService;
import cn.edu.xmu.oomall.share.microservice.OrderService;
import cn.edu.xmu.oomall.share.microservice.vo.*;
import cn.edu.xmu.oomall.share.microservice.vo.RebateLevel;
import cn.edu.xmu.oomall.share.model.bo.Share;
import cn.edu.xmu.oomall.share.model.bo.SuccessfulShare;
import cn.edu.xmu.oomall.share.model.po.SharePo;
import cn.edu.xmu.oomall.share.model.po.SharePoExample;
import cn.edu.xmu.oomall.share.model.po.SuccessfulSharePo;
import cn.edu.xmu.oomall.share.model.po.SuccessfulSharePoExample;
import cn.edu.xmu.oomall.share.model.vo.PointRetVo;
import cn.edu.xmu.oomall.share.model.vo.ShareRetVo;
import cn.edu.xmu.oomall.share.model.vo.SimpleCustomerRetVo;
import cn.edu.xmu.oomall.share.model.vo.SuccessfulShareRetVo;
import cn.edu.xmu.oomall.share.utility.MyPageHelper;
import cn.edu.xmu.privilegegateway.annotation.util.InternalReturnObject;
import cn.edu.xmu.privilegegateway.annotation.util.JacksonUtil;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.alibaba.fastjson.JSON;

import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.List;


import static cn.edu.xmu.privilegegateway.annotation.util.Common.cloneVo;
import static cn.edu.xmu.privilegegateway.annotation.util.Common.setPoCreatedFields;

/**
 * @author Jianxiang Xie
 * @date 2021/12/5
 */

@Slf4j
@Service
public class ShareService {

    @Autowired
    ShareDao shareDao;

    @Autowired
    GoodsService goodsService;

    @Autowired
    OrderService orderService;

    @Autowired
    ActivityService activityService;

    /**
     * 分享者生成分享链接
     *
     * @param onsaleId      onsaleid
     * @param loginUserId   用户id
     * @param loginUserName 用户名
     * @return shareRetVo
     */
    public ReturnObject genShare(Long onsaleId, Long loginUserId, String loginUserName) {

        try {
            //获取onsaleid对应的Onsale
            InternalReturnObject<OnSaleRetVo> internalReturn = goodsService.getOnSaleRetVo(onsaleId);
            if (!internalReturn.getErrno().equals(ReturnNo.OK.getCode())) {
                return new ReturnObject(ReturnNo.INTERNAL_SERVER_ERR, internalReturn.getErrmsg());
            }
            //OnSaleRetVo onSaleRetVo = JSON.parseObject(JacksonUtil.toJson(internalReturn.getData()), OnSaleRetVo.class);
            OnSaleRetVo onSaleRetVo = internalReturn.getData();
            var ret2 = activityService.getShareActivityById(onSaleRetVo.getShareActId());
            if (ret2.getData() == null) {
                return new ReturnObject(ReturnNo.SHARE_UNSHARABLE, ReturnNo.SHARE_UNSHARABLE.getMessage());
            }

            //构建用于插入的BO对象
            Share share = new Share();
            share.setSharerId(loginUserId);
            share.setShareActId(onSaleRetVo.getShareActId());
            share.setProductId(onSaleRetVo.getProduct().getId());
            share.setOnsaleId(onSaleRetVo.getId());
            share.setQuantity(0L);
            share.setState(Share.State.VALID.getCode().byteValue());
            setPoCreatedFields(share, loginUserId, loginUserName);
            //dao层插入
            var daoRet = shareDao.insertShare(share);
            if (!daoRet.getCode().equals(ReturnNo.OK)) {
                return daoRet;
            }
            //构建返回对象
            Share newShare = (Share) daoRet.getData();
            ShareRetVo shareRetVo = cloneVo(newShare, ShareRetVo.class);
            //顾客
            shareRetVo.setSharer(new SimpleCustomerRetVo(loginUserId, loginUserName));
            shareRetVo.setProduct(onSaleRetVo.getProduct());
            shareRetVo.setCreator(new SimpleAdminUserBo(newShare.getCreatorId(), newShare.getCreatorName()));
            shareRetVo.setModifier(new SimpleAdminUserBo(newShare.getModifierId(), newShare.getModifierName()));
            return new ReturnObject(shareRetVo);
        } catch (Exception e) {
            e.printStackTrace();
            return new ReturnObject(ReturnNo.INTERNAL_SERVER_ERR);
        }
    }


    /**
     * 根据条件获取分享记录
     *
     * @param did         shopId
     * @param loginUserId 登录的用户id
     * @param productId   货品id
     * @param beginTime   创建时间区间的开始时间
     * @param endTime     区间结束时间
     * @param page        页
     * @param pageSize    页大小
     * @return 分享记录
     */
    @Transactional(readOnly = true, rollbackFor = Exception.class)
    public ReturnObject getSharesByConditions(Long did, Long loginUserId, Long productId, ZonedDateTime beginTime, ZonedDateTime endTime, Integer page, Integer pageSize) {
        SharePoExample sharePoExample = new SharePoExample();
        SharePoExample.Criteria criteria = sharePoExample.createCriteria();
        //设置可选条件
        if (productId != null) {
            criteria.andProductIdEqualTo(productId);
        }
        if (beginTime != null) {
            criteria.andGmtCreateGreaterThan(beginTime.toLocalDateTime());
        }
        if (endTime != null) {
            criteria.andGmtCreateLessThan(endTime.toLocalDateTime());
        }
        if (loginUserId != null) {
            criteria.andSharerIdEqualTo(loginUserId);
        }
        //dao层查找
        var ret = shareDao.getSharePosByExampleWithPage(sharePoExample, page, pageSize);
        if (!ret.getCode().equals(ReturnNo.OK)) {
            return ret;
        }
        //利用SharePo列表构建ShareRetVo列表
        PageInfo<Share> pageInfo = (PageInfo<Share>) ret.getData();
        List<Share> sharePos = pageInfo.getList();
        var ret1 = getShareRetVo(sharePos, did != null, did);
        if (!ret1.getCode().equals(ReturnNo.OK)) {
            return ret1;
        }
        List<ShareRetVo> shareRetVos = ret1.getData();
        PageInfo<ShareRetVo> retPageInfo = new PageInfo<>(shareRetVos);
        MyPageHelper.transferPageParams(pageInfo, retPageInfo);
        ReturnObject returnObject = new ReturnObject<>(retPageInfo);
        return Common.getPageRetVo(returnObject, ShareRetVo.class);
    }

    /**
     * 获取分享记录中的商品详情
     *
     * @param sid         分享id
     * @param productId   货品id
     * @param loginUserId 登录用户id
     * @return 商品详情
     */
    @Transactional(readOnly = true, rollbackFor = Exception.class)
    public ReturnObject getProductByShareId(Long sid, Long productId, Long loginUserId) {
        //先通过sid查出对应的share
        var ret = getShareById(sid);
        if (!ret.getCode().equals(ReturnNo.OK)) {
            return ret;
        }
        Share share = (Share) ret.getData();

        //检查传入的loginUserId与Share的SharerId是否不同
        if (loginUserId.longValue() != share.getSharerId().longValue()) {
            return new ReturnObject(ReturnNo.RESOURCE_ID_OUTSCOPE, ReturnNo.RESOURCE_ID_OUTSCOPE.getMessage());
        }
        //检查传入的productId与Share的productId是否不同
        if (productId.longValue() != share.getProductId().longValue()) {
            return new ReturnObject(ReturnNo.RESOURCE_ID_OUTSCOPE, ReturnNo.RESOURCE_ID_OUTSCOPE.getMessage());
        }
        //通过sharePo的ProductId找出Product
        var internalRet2 = goodsService.getProductDetail(productId);
        if (!internalRet2.getErrno().equals(ReturnNo.OK.getCode())) {
            return new ReturnObject(ReturnNo.INTERNAL_SERVER_ERR, internalRet2.getErrmsg());
        }
        ProductRetVo product = internalRet2.getData();
        product.setOnSaleId(share.getOnsaleId());
        return new ReturnObject(product);
    }

    /**
     * 根据条件获取分享成功的记录
     *
     * @param loginUserId 用户id
     * @param did         shopId
     * @param productId   货品id
     * @param beginTime   开始时间
     * @param endTime     结束时间
     * @param page        页
     * @param pageSize    页大小
     * @return 分享成功记录
     */
    @Transactional(readOnly = true, rollbackFor = Exception.class)
    public ReturnObject getSuccessfulSharesByConditions(Long loginUserId, Long did, Long productId, ZonedDateTime beginTime, ZonedDateTime endTime, Integer page, Integer pageSize) {
        SuccessfulSharePoExample example = new SuccessfulSharePoExample();
        SuccessfulSharePoExample.Criteria criteria = example.createCriteria();
        //设置可选条件
        if (productId != null) {
            criteria.andProductIdEqualTo(productId);
        }
        if (beginTime != null) {
            criteria.andGmtCreateGreaterThan(beginTime.toLocalDateTime());
        }
        if (endTime != null) {
            criteria.andGmtCreateLessThan(endTime.toLocalDateTime());
        }
        if (loginUserId != null) {
            criteria.andSharerIdEqualTo(loginUserId);
        }
        //dao层查找
        var ret = shareDao.getSuccessfulSharePosByExampleWithPage(example, page, pageSize);
        if (!ret.getCode().equals(ReturnNo.OK)) {
            return ret;
        }
        PageInfo<SuccessfulShare> pageInfo = (PageInfo<SuccessfulShare>) ret.getData();
        List<SuccessfulShare> successfulSharePos = pageInfo.getList();
        var ret1 = getSuccessfulShareRetVo(successfulSharePos, did != null, did);
        if (!ret1.getCode().equals(ReturnNo.OK)) {
            return ret1;
        }
        List<SuccessfulShareRetVo> successfulShareRetVos = ret1.getData();
        PageInfo<SuccessfulShareRetVo> retVoPageInfo = new PageInfo<>(successfulShareRetVos);
        MyPageHelper.transferPageParams(pageInfo, retVoPageInfo);
        ReturnObject returnObject = new ReturnObject(retVoPageInfo);
        return Common.getPageRetVo(returnObject, SuccessfulShareRetVo.class);
    }

    public SuccessfulShare getEarliestSuccessfulShare(Long customerId, Long onSaleId) {
        //设置查询条件
        SuccessfulSharePoExample example = new SuccessfulSharePoExample();
        SuccessfulSharePoExample.Criteria criteria = example.createCriteria();
        //设置以创建时间升序，限制只查一条
        example.setOrderByClause("gmt_create ASC limit 1");
        criteria.andCustomerIdEqualTo(customerId);
        criteria.andOnsaleIdEqualTo(onSaleId);
        var ret = shareDao.getSuccessfulSharePosByExample(example);
        List<SuccessfulShare> successfulSharePos = (List<SuccessfulShare>) ret.getData();
        if (successfulSharePos != null) {
            return successfulSharePos.get(0);
        } else {
            return null;
        }
    }

    public ReturnObject getShareById(Long shareId) {
        SharePoExample sharePoExample = new SharePoExample();
        SharePoExample.Criteria criteria = sharePoExample.createCriteria();
        criteria.andIdEqualTo(shareId);
        var daoRet = shareDao.getSharePosByExample(sharePoExample);
        if (!daoRet.getCode().equals(ReturnNo.OK)) {
            return daoRet;
        }
        Share share = ((List<Share>) daoRet.getData()).get(0);
        return new ReturnObject(share);
    }

    public ReturnObject updateSuccessfulShare(Long successfulShareId, Byte state) {
        SuccessfulSharePo successfulSharePo = new SuccessfulSharePo();
        successfulSharePo.setId(successfulShareId);
        successfulSharePo.setState(state);
        var ret = shareDao.updateSuccessfulShareByPo(successfulSharePo);
        if (!ret.getCode().equals(ReturnNo.OK)) {
            return ret;
        }
        return new ReturnObject();
    }

    public ReturnObject updateShare(Long shareId, Long orderItemQuantity) {
        //先通过sid查出对应的share
        var ret = getShareById(shareId);
        if (!ret.getCode().equals(ReturnNo.OK)) {
            return ret;
        }
        Share share = (Share) ret.getData();
        share.setQuantity(share.getQuantity() + orderItemQuantity);
        var daoRet = shareDao.updateShareByPo(cloneVo(share, SharePo.class));
        if (!daoRet.getCode().equals(ReturnNo.OK)) {
            return daoRet;
        }
        return new ReturnObject();
    }


    public ReturnObject calculate(Long orderItemId) {
        double point = 0;
        try {
            //获取OrderItem
            var ret1 = orderService.getOrderItemById(orderItemId);
            if (!ret1.getErrno().equals(0)) {
                return new ReturnObject(ReturnNo.getByCode(ret1.getErrno()), ret1.getErrmsg());
            }
            //OrderItemVo orderItemVo = JSON.parseObject(JacksonUtil.toJson(ret1.getData()), OrderItemVo.class);
            OrderItemVo orderItemVo = ret1.getData();
            //获取order 来获取分享者的id
            var ret2 = orderService.getOrderById(orderItemVo.getOrderId());
            if (!ret2.getErrno().equals(0)) {
                return new ReturnObject(ReturnNo.getByCode(ret2.getErrno()), ret2.getErrmsg());
            }
            //SimpleOrderVo simpleOrderVo = JSON.parseObject(JacksonUtil.toJson(ret2.getData()), SimpleOrderVo.class);
            SimpleOrderVo simpleOrderVo = ret2.getData();
            //获取最早的分享成功记录
            SuccessfulShare successfulShare = getEarliestSuccessfulShare(simpleOrderVo.getCustomerId(), orderItemVo.getOnSaleId());
            if (successfulShare != null) {
                var ret3 = goodsService.getOnSaleRetVo(orderItemVo.getOnSaleId());
                if (!ret3.getErrno().equals(0)) {
                    return new ReturnObject(ReturnNo.getByCode(ret3.getErrno()), ret3.getErrmsg());
                }
                //OnSaleRetVo onSaleRetVo = JSON.parseObject(JacksonUtil.toJson(ret3.getData()), OnSaleRetVo.class);
                OnSaleRetVo onSaleRetVo = ret3.getData();
                InternalReturnObject<ShareActivityVo> ret4 = activityService.getShareActivityById(onSaleRetVo.getShareActId());
                if (!ret4.getErrno().equals(0)) {
                    return new ReturnObject(ReturnNo.getByCode(ret4.getErrno()), ret4.getErrmsg());
                }
                //ShareActivityVo shareActivityVo = JSON.parseObject(JacksonUtil.toJson(ret4.getData()), ShareActivityVo.class);
                ShareActivityVo shareActivityVo = ret4.getData();
                Share share = (Share) getShareById(successfulShare.getShareId()).getData();
                //percentage为千分位
                Double percentage = getPercentage(shareActivityVo.getStrategy(), share.getQuantity(), orderItemVo.getQuantity());
                //price 单位为分，discount_price 单位为1/10分 先将他们都转化为1/10分为单位，再除1000转换为元
                Long actualFee = (orderItemVo.getPrice() * 10 - orderItemVo.getDiscountPrice()) * orderItemVo.getQuantity() / 1000;
                point = (percentage / 1000) * actualFee;
                updateShare(share.getId(), orderItemVo.getQuantity());
                updateSuccessfulShare(successfulShare.getId(), (byte) 1);
            }
            return new ReturnObject(new PointRetVo(point, successfulShare == null ? null : successfulShare.getSharerId()));
        } catch (Exception e) {
            e.printStackTrace();
            return new ReturnObject(ReturnNo.INTERNAL_SERVER_ERR, ReturnNo.INTERNAL_SERVER_ERR.getMessage());
        }
    }

    public Double getPercentage(List<RebateLevel> strategy, Long quantity, Long orderItemQuantity) {
        Long total = quantity + orderItemQuantity;
        double percentage = 0;
        for (RebateLevel rebateLevel : strategy) {
            if (total <= rebateLevel.getQuantity()) {
                break;
            }
            percentage = rebateLevel.getPercentage();
        }
        return percentage;
    }

    /**
     * 将SharePo转化成功ShareRetVo(根据ProductId查找出对应到Product)
     *
     * @param shares      Share列表
     * @param checkShopId 是否检查ShopId
     * @param shopId      shopId
     * @return ShareRetVo列表
     */
    public ReturnObject<List<ShareRetVo>> getShareRetVo(List<Share> shares, boolean checkShopId, Long shopId) {
        //利用SharePo列表构建ShareRetVo列表
        //可带shopId的检查
        List<ShareRetVo> shareRetVos = new ArrayList<>();
        try {
            for (Share share : shares) {
                System.out.println("share" + share);
                ShareRetVo shareRetVo = cloneVo(share, ShareRetVo.class);
                System.out.println("shareRetVo" + shareRetVo);
                //通过SharePo的的onSaleId获得OnSaleRetVo
                //将OnSaleRetVo赋给shareRetVo
                InternalReturnObject<OnSaleRetVo> internalRet = goodsService.getOnSaleRetVo(share.getOnsaleId());
                if (internalRet.getErrno().equals(ReturnNo.OK.getCode())) {
                    //OnSaleRetVo onSaleVo = JSON.parseObject(JacksonUtil.toJson(internalRet.getData()), OnSaleRetVo.class);
                    OnSaleRetVo onSaleVo = internalRet.getData();
                    //如果需要检查shopId,则shopId不同的product不添加
                    if (checkShopId) {
                        if (onSaleVo.getShop().getId().longValue() != shopId.longValue()) {
                            return new ReturnObject<>(ReturnNo.RESOURCE_ID_OUTSCOPE,ReturnNo.RESOURCE_ID_OUTSCOPE.getMessage());
                        }
                    }
                    shareRetVo.setProduct(onSaleVo.getProduct());
                }
                //设置对象属性
                shareRetVo.setSharer(new SimpleCustomerRetVo(share.getSharerId(), share.getCreatorName()));
                shareRetVo.setCreator(new SimpleAdminUserBo(share.getCreatorId(), share.getCreatorName()));
                shareRetVo.setModifier(new SimpleAdminUserBo(share.getModifierId(), share.getModifierName()));
                shareRetVos.add(shareRetVo);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return new ReturnObject<>(shareRetVos);
    }

    /**
     * 将SuccessfulSharePo转化成功SuccessfulShareRetVo(根据ProductId查找出对应到Product)
     *
     * @param successfulShares List<SuccessfulShare>
     * @param checkShopId      是否检查ShopId
     * @param shopId           shopId
     * @return List<SuccessfulShareRetVo>
     */
    public ReturnObject<List<SuccessfulShareRetVo>> getSuccessfulShareRetVo(List<SuccessfulShare> successfulShares, boolean checkShopId, Long shopId) {
        List<SuccessfulShareRetVo> successfulShareRetVos = new ArrayList<>();

        try {
            for (SuccessfulShare successfulShare : successfulShares) {
                SuccessfulShareRetVo successfulShareRetVo = cloneVo(successfulShare, SuccessfulShareRetVo.class);
                InternalReturnObject<OnSaleRetVo> internalRet2 = goodsService.getOnSaleRetVo(successfulShare.getOnsaleId());
                if (internalRet2.getErrno().equals(ReturnNo.OK.getCode())) {
                    //OnSaleRetVo onSaleVo = JSON.parseObject(JacksonUtil.toJson(internalRet2.getData()), OnSaleRetVo.class);
                    OnSaleRetVo onSaleVo = internalRet2.getData();
                    //如果需要检查shopId,则shopId不同的product不添加
                    if (checkShopId) {
                        if (onSaleVo.getShop().getId().longValue() != shopId.longValue()) {
                            return new ReturnObject<>(ReturnNo.RESOURCE_ID_OUTSCOPE,ReturnNo.RESOURCE_ID_OUTSCOPE.getMessage());
                        }
                    }
                    successfulShareRetVo.setProduct(onSaleVo.getProduct());
                }
                successfulShareRetVo.setCreator(new SimpleAdminUserBo(successfulShare.getCreatorId(), successfulShare.getCreatorName()));
                successfulShareRetVo.setModifier(new SimpleAdminUserBo(successfulShare.getModifierId(), successfulShare.getModifierName()));
                successfulShareRetVos.add(successfulShareRetVo);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new ReturnObject<>(successfulShareRetVos);
    }
}